package tmt.usercenter.web.controller;

import com.tmt.helper.DateHelper;
import com.tmt.helper.DesHelper;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.savedrequest.DefaultSavedRequest;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import tmt.usercenter.web.Application;
import tmt.usercenter.web.configure.security.bean.TmtServerSessionRegistry;
import tmt.usercenter.web.domain.security.UserDetailsImpl;
import tmt.usercenter.web.service.BaseComponent;
import tmt.usercenter.web.utils.HttpServletRequestHelper;
import tmt.usercenter.web.vo.Notify;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.beans.PropertyEditorSupport;
import java.util.*;

/**
 * 基础组件
 * Created by Stark on 2017/3/2.
 */
@Component
public class BaseController extends BaseComponent {

	public static final String NOTIFY = "__NOTIFY";

	public static final String INTRODUCER_CODE = "ic";

	@InitBinder
	protected void initBinder(WebDataBinder binder) {
		binder.registerCustomEditor(Date.class, new DateEditor(DateHelper.DATE_TIME_FORMAT));
	}

	@ModelAttribute("isMobile")
	public boolean isMobile(HttpServletRequest request) {
		return HttpServletRequestHelper.isMobileDevice(request);
	}

	/**
	 * 往前台发送通知。适用于初始页面显示。暂不允许跳转页面信息提示
	 *
	 * @param model  数据载体
	 * @param notify 通知
	 */
	protected void notify(Model model, Notify notify) {
		Objects.requireNonNull(model, "model can't be null.");
		Objects.requireNonNull(notify, "notify can't be null.");

		Optional<List<Notify>> o = Optional.ofNullable((List<Notify>) model.asMap().get(NOTIFY));
		List<Notify> list = o.orElse(new ArrayList<>());
		list.add(notify);

		model.addAttribute(NOTIFY, list);
	}

	public Long getIntroducerCode(HttpServletRequest request) {
		Long introducerCode = (Long) request.getSession().getAttribute(INTRODUCER_CODE);
		if (introducerCode != null)
			return introducerCode;

		try {
			//从参数中获取
			String code = request.getParameter(INTRODUCER_CODE);
			if (code != null) {
				code = DesHelper.decrypt(code);
				introducerCode = Long.parseLong(code);
				//保存到Session中去。
				request.getSession().setAttribute(INTRODUCER_CODE, introducerCode);
			}
		} catch (Exception ex) {
		}
		return null;
	}

	public String getClientId(HttpServletRequest request) {
		return getClientId(request, true);
	}

	public String getClientId(HttpServletRequest request, boolean decode) {
		//首先从参数上获取
		String clientId = request.getParameter(TmtServerSessionRegistry.CLIENT_ID);
		if (clientId != null && decode) {
			try {
				clientId = DesHelper.decrypt(clientId);
			} catch (Exception ex) {
			}
		}

		//从Session中获取
		if (clientId == null)
			clientId = (String) request.getSession().getAttribute(TmtServerSessionRegistry.CLIENT_ID);

		//从安全上下文中获取。
		if (clientId == null)
			clientId = getClientIdFromSecurityContext(request.getSession());

		//更新到Session中去。
		request.getSession().setAttribute(TmtServerSessionRegistry.CLIENT_ID, clientId);
		return clientId;
	}

	private String getClientIdFromSecurityContext(HttpSession session) {
		String clientId = null;
		try {
			Object savedRequest = session.getAttribute("SPRING_SECURITY_SAVED_REQUEST");
			if (savedRequest != null) {
				clientId = ((DefaultSavedRequest) savedRequest).getParameterMap().get(TmtServerSessionRegistry.CLIENT_ID)[0];
			} else {
				UserDetailsImpl userDetails = (UserDetailsImpl) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
				if (userDetails != null)
					clientId = userDetails.getClientId();
			}
		} catch (Exception ex) {
		}
		return !StringUtils.isEmpty(clientId) ? clientId : Application.SYSTEM_ID;
	}

	public static class DateEditor extends PropertyEditorSupport {
		private final String formatPattern;

		public DateEditor(String formatPattern) {
			this.formatPattern = formatPattern;
		}

		@Override
		public void setAsText(String text) {
			if (!StringUtils.hasText(text)) {
				setValue(null);
			} else {
				setValue(DateHelper.parseDate(text));
			}
		}

		/**
		 * Format the Date as String, using the specified DateFormat.
		 */
		@Override
		public String getAsText() {
			Date value = (Date) getValue();
			return (value != null ? DateHelper.formatDate(value, formatPattern) : "");
		}
	}
}
